﻿' ******************************************************************************
' ** 
' **  Yahoo Finance Managed
' **  Written by Marius Häusler 2010
' **  It would be pleasant, if you contact me when you are using this code.
' **  Contact: YahooFinanceManaged@gmail.com
' **  Project Home: http://code.google.com/p/yahoo-finance-managed/
' **  
' ******************************************************************************
' **  
' **  Copyright 2010 Marius Häusler
' **  
' **  Licensed under the Apache License, Version 2.0 (the "License");
' **  you may not use this file except in compliance with the License.
' **  You may obtain a copy of the License at
' **  
' **    http://www.apache.org/licenses/LICENSE-2.0
' **  
' **  Unless required by applicable law or agreed to in writing, software
' **  distributed under the License is distributed on an "AS IS" BASIS,
' **  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' **  See the License for the specific language governing permissions and
' **  limitations under the License.
' ** 
' ******************************************************************************


Namespace RSS.ImportExport

    Public Class XML
        Private ReadOnly mHelper As New MyHelper
        Public Function ToFeed(ByVal channel As XmlNode) As Feed
            If channel.Name.ToLower = "channel" Then
                Dim feed As New Feed
                For Each prpNode As XmlNode In channel.ChildNodes
                    Try
                        Select Case prpNode.Name.ToLower
                            Case "category"
                                feed.Category = New Category
                                feed.Category.Name = prpNode.InnerText
                                If prpNode.Attributes.Count = 1 Then feed.Category.Domain = New Uri(prpNode.Item("domain").InnerText)
                            Case "cloud"
                                feed.Cloud = New Cloud
                                For Each att As XmlAttribute In prpNode.Attributes
                                    Select Case att.Name.ToLower
                                        Case "domain" : feed.Cloud.Domain = New Uri(att.InnerText)
                                        Case "path" : feed.Cloud.Path = att.InnerText
                                        Case "registerprocedure" : feed.Cloud.RegisterProcedure = att.InnerText
                                        Case "protocol" : feed.Cloud.Protocol = att.InnerText
                                        Case "port" : Integer.TryParse(att.InnerText, feed.Cloud.Port)
                                    End Select
                                Next
                            Case "copyright" : feed.Copyright = prpNode.InnerText
                            Case "description" : feed.Description = prpNode.InnerText
                            Case "docs" : feed.Documentation = New Uri(prpNode.InnerText)
                            Case "generator" : feed.Generator = prpNode.InnerText
                            Case "link" : feed.Link = New Uri(prpNode.InnerText)
                            Case "language" : feed.Language = New Globalization.CultureInfo(prpNode.InnerText)
                            Case "lastbuilddate" : feed.LastBuildDate = Me.RFC822DateFromString(prpNode.InnerText)
                            Case "managingeditor" : feed.ManagingEditor = Me.Rss2MailToMailAddress(prpNode.InnerText)
                            Case "name" : feed.Name = prpNode.InnerText
                            Case "image"
                                feed.Image = New Image
                                For Each nodeChild As XmlNode In prpNode.ChildNodes
                                    Select Case nodeChild.Name.ToLower
                                        Case "url" : feed.Image.URL = New Uri(nodeChild.InnerText)
                                        Case "link" : feed.Image.Link = New Uri(nodeChild.InnerText)
                                        Case "title" : feed.Image.Title = nodeChild.InnerText
                                        Case "description" : feed.Image.Description = nodeChild.InnerText
                                        Case "width" : Integer.TryParse(nodeChild.InnerText, feed.Image.Width)
                                        Case "height" : Integer.TryParse(nodeChild.InnerText, feed.Image.Height)
                                    End Select
                                Next
                            Case "item"
                                Dim rssItem As FeedItem = Me.ToFeedItem(prpNode)
                                If rssItem IsNot Nothing Then feed.Items.Add(rssItem)
                            Case "pubdate" : feed.PublishDate = Me.RFC822DateFromString(prpNode.InnerText)
                            Case "rating" : feed.Rating = prpNode.InnerText
                            Case "skiphours"
                                Dim lst As New List(Of Integer)
                                For Each nodeChild As XmlNode In prpNode.ChildNodes
                                    If nodeChild.Name.ToLower = "hour" Then
                                        Dim int As Integer
                                        If Integer.TryParse(nodeChild.InnerText, int) Then lst.Add(int)
                                    End If
                                Next
                                feed.Skiphours = lst.ToArray
                            Case "skipdays"
                                Dim lst As New List(Of DayOfWeek)
                                For Each nodeChild As XmlNode In prpNode.ChildNodes
                                    If nodeChild.Name.ToLower = "day" Then
                                        For i As Integer = 0 To DayOfWeek.Saturday
                                            If DirectCast(i, DayOfWeek).ToString.ToUpper = nodeChild.InnerText.ToUpper Then
                                                lst.Add(DirectCast(i, DayOfWeek))
                                                Exit For
                                            End If
                                        Next
                                    End If
                                Next
                                feed.Skipdays = lst.ToArray
                            Case "textinput"
                                feed.TextInput = New TextInputBox
                                For Each nodeChild As XmlNode In prpNode.ChildNodes
                                    Select Case nodeChild.Name.ToLower
                                        Case "name" : feed.TextInput.Name = nodeChild.InnerText
                                        Case "link" : feed.TextInput.Link = New Uri(nodeChild.InnerText)
                                        Case "title" : feed.TextInput.Title = nodeChild.InnerText
                                        Case "description" : feed.TextInput.Description = nodeChild.InnerText
                                    End Select
                                Next

                            Case "title" : feed.Title = prpNode.InnerText
                            Case "ttl" : feed.Ttl = Convert.ToInt32(prpNode.InnerText)

                            Case "webmaster" : feed.Webmaster = Me.Rss2MailToMailAddress(prpNode.InnerText)
                            Case Else
                                'Debug.WriteLine(node.Name)
                        End Select
                    Catch ex As Exception
                    End Try
                Next
                Return feed
            Else
                Return Nothing
            End If
        End Function
        Friend Function ToFeedItem(ByVal item As XmlNode) As FeedItem
            If item.Name = "item" Then
                Dim rssItem As New FeedItem()
                For Each itemNode As XmlNode In item.ChildNodes
                    Try
                        Select Case itemNode.Name.ToLower
                            Case "title" : rssItem.Title = itemNode.InnerText
                            Case "link" : rssItem.Link = New Uri(itemNode.InnerText)
                            Case "description" : rssItem.Description = itemNode.InnerText
                            Case "author" : rssItem.Author = itemNode.InnerText
                            Case "category"
                                rssItem.Category = New Category
                                rssItem.Category.Name = itemNode.InnerText
                                If itemNode.Attributes.Count = 1 Then rssItem.Category.Domain = New Uri(itemNode.Attributes("domain").InnerText)
                            Case "comments" : rssItem.Comments = New Uri(itemNode.InnerText)
                            Case "enclosure"
                                rssItem.Enclosure = New Enclosure
                                rssItem.Enclosure.Url = New Uri(itemNode.Item("url").InnerText)
                                Long.TryParse(itemNode.Item("length").InnerText, rssItem.Enclosure.Length)
                                rssItem.Enclosure.Type = itemNode.Item("type").InnerText
                            Case "guid"
                                rssItem.GUID = New GUID
                                rssItem.GUID.ID = itemNode.InnerText
                                If itemNode.Attributes.Count = 1 Then rssItem.GUID.IsPermaLink = CBool(itemNode.Attributes("isPermaLink").InnerText)
                            Case "pubdate" : rssItem.PublishDate = Me.RFC822DateFromString(itemNode.InnerText)
                            Case "insertdate" : rssItem.InsertDate = Me.RFC822DateFromString(item.InnerText)
                            Case "source"
                                rssItem.Source = New Source
                                rssItem.Source.Title = itemNode.InnerText
                                rssItem.Source.Url = New Uri(itemNode.Item("url").InnerText)
                            Case Else
                                'Debug.WriteLine(itemNode.Name)
                        End Select
                    Catch ex As Exception
                    End Try
                Next
                Return rssItem
            End If
            Return Nothing
        End Function
        Private Function RFC822DateFromString(ByVal d As String) As System.DateTime
            Dim result As System.DateTime
            If d <> String.Empty Then
                Dim spacePos As Integer = d.LastIndexOf(" ")
                Dim timezone As String = d.Substring(spacePos + 1)

                If Date.TryParse(d, result) Then
                    If timezone = "Z" Or timezone = "GMT" Then result = result.ToUniversalTime()
                    Return result
                Else
                    result = Convert.ToDateTime(d.Substring(0, spacePos))
                    If d(spacePos + 1) = "+"c Then
                        result = result.AddHours(-1 * Convert.ToInt32(d.Substring(spacePos + 2, 2)))
                        result = result.AddMinutes(-1 * Convert.ToInt32(d.Substring(spacePos + 4, 2)))
                    ElseIf d(spacePos + 1) = "-"c Then
                        Dim h As Integer = Convert.ToInt32(d.Substring(spacePos + 2, 2))
                        result = result.AddHours(h)
                        Dim m As Integer = Convert.ToInt32(d.Substring(spacePos + 4, 2))
                        result = result.AddMinutes(m)
                    Else
                        Select Case timezone
                            Case "A" : result = result.AddHours(1)
                            Case "B" : result = result.AddHours(2)
                            Case "C" : result = result.AddHours(3)
                            Case "D" : result = result.AddHours(4)
                            Case "EDT" : result = result.AddHours(4)
                            Case "E" : result = result.AddHours(5)
                            Case "EST" : result = result.AddHours(5)
                            Case "CDT" : result = result.AddHours(5)
                            Case "F" : result = result.AddHours(6)
                            Case "CST" : result = result.AddHours(6)
                            Case "MDT" : result = result.AddHours(6)
                            Case "G" : result = result.AddHours(7)
                            Case "MST" : result = result.AddHours(7)
                            Case "PDT" : result = result.AddHours(7)
                            Case "H" : result = result.AddHours(8)
                            Case "PST" : result = result.AddHours(8)
                            Case "I" : result = result.AddHours(9)
                            Case "K" : result = result.AddHours(10)
                            Case "L" : result = result.AddHours(11)
                            Case "M" : result = result.AddHours(12)
                            Case "N" : result = result.AddHours(-1)
                            Case "O" : result = result.AddHours(-2)
                            Case "P" : result = result.AddHours(-3)
                            Case "Q" : result = result.AddHours(-4)
                            Case "R" : result = result.AddHours(-5)
                            Case "S" : result = result.AddHours(-6)
                            Case "T" : result = result.AddHours(-7)
                            Case "U" : result = result.AddHours(-8)
                            Case "V" : result = result.AddHours(-9)
                            Case "W" : result = result.AddHours(-10)
                            Case "X" : result = result.AddHours(-11)
                            Case "Y" : result = result.AddHours(-12)
                        End Select
                    End If
                End If
            End If
            Return result
        End Function
        Private Function Rss2MailToMailAddress(ByVal address As String) As Mail.MailAddress
            If address <> String.Empty Then
                Try
                    Dim ind As Integer = address.IndexOf("("c)
                    If ind > -1 Then
                        Dim adr As String = address.Substring(0, ind).Trim
                        Dim name As String = address.Substring(ind).Replace("(", "").Replace(")", "").Trim
                        Return New Mail.MailAddress(adr, name)
                    Else
                        Return New Mail.MailAddress(address)
                    End If
                Catch ex As Exception
                    Return Nothing
                End Try
            Else
                Return Nothing
            End If
        End Function
    End Class

End Namespace